/**    
 * 文件名：BillCancelService.java</br>
 *    
 * 版本信息：v1.0</br>
 * 日期：2017年8月17日</br>
 * © 2005-2017 雷技信息科技（上海）有限公司版权所有</br>
 *
 */
package com.logic.landseaserver.models.independent.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.logic.common.security.SecurityUtils;
import com.logic.landseaserver.common.LandeaConstants;
import com.logic.landseaserver.common.LandeaConstants.ProduceType;
import com.logic.landseaserver.common.enums.BTypeEnum;
import com.logic.landseaserver.common.enums.BillStatusEnum;
import com.logic.landseaserver.common.enums.BillTypeEnum;
import com.logic.landseaserver.common.exception.LandseaException;
import com.logic.landseaserver.domain.BalanceSheetRecord;
import com.logic.landseaserver.domain.Bill;
import com.logic.landseaserver.domain.BillDetail;
import com.logic.landseaserver.domain.Contract;
import com.logic.landseaserver.domain.Deposit;
import com.logic.landseaserver.domain.RealBill;
import com.logic.landseaserver.domain.Room;
import com.logic.landseaserver.models.independent.AuthCodeBillTypeGetter;
import com.logic.landseaserver.persistence.read.BalanceSheetRecordReadMapper;
import com.logic.landseaserver.persistence.read.BillDetailReadMapper;
import com.logic.landseaserver.persistence.read.BillReadMapper;
import com.logic.landseaserver.persistence.read.ContractReadMapper;
import com.logic.landseaserver.persistence.read.DepositReadMapper;
import com.logic.landseaserver.persistence.read.RealBillReadMapper;
import com.logic.landseaserver.persistence.read.RoomReadMapper;
import com.logic.landseaserver.persistence.write.BalanceSheetRecordWriteMapper;
import com.logic.landseaserver.ws.dto.CurrentBillDTO;

/**
 *
 * 项目名称：system-server</br>
 * 类名称：BillIndependentService</br>
 * 类描述：独立账单</br>
 * 创建人：Crystal</br>
 * 创建时间：2017年8月31日 下午10:25:56</br>
 * 
 * @version 1.0
 *
 */
@Service
public class BillIndependentService
{
    private static final Logger log = LoggerFactory.getLogger(BillIndependentService.class);

    @Autowired
    private BalanceSheetRecordWriteMapper balanceSheetWriteMapper;
    
    @Autowired
    private BillDetailReadMapper billDetailReadMapper;
    
    @Autowired
    private BillReadMapper billReadMapper;
    
    @Autowired
    private DepositReadMapper depositReadMapper;
    
    @Autowired
    private RealBillReadMapper realBillReadMapper;
    
    @Autowired
    private BalanceSheetRecordReadMapper balanceSheetRecordReadMapper;
    
    @Autowired
    private ContractReadMapper contractReadMapper;
    
    @Autowired
    private RoomReadMapper roomReadMapper;
    
    /**
     * 
     * [简要描述]：独立账单</br>
     * [详细描述]：独立账单的插入操作</br>
     * [作者]：Crystal(2017-08-31)</br>
     *
     * @throws LandseaException
     *
     */
    public void insertBalanceSheet(BalanceSheetRecord record)
        throws LandseaException
    {
        record.setCreateTime(new Date());
        record.setLastModifiedBy(SecurityUtils.getCurrentLogin().getUserId());
        record.setLastModifiedDtm(new Date());
        balanceSheetWriteMapper.insertSelective(record);
    }
    
    /**
     * 
     * [简要描述]：通过月结账单新增独立账单</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-10-20)</br>
     *
     * @throws LandseaException
     *
     */
    public void insertFromMonth(List<BillDetail> billDetailList, Contract contract, Bill bill) throws LandseaException
    {
        // 入独立账单
        Room room = roomReadMapper.selectByPrimaryKey(contract.getRoomId());
        for (BillDetail billTail : billDetailList)
        {
            BalanceSheetRecord balanceSheetRecord = new BalanceSheetRecord();
            balanceSheetRecord.setContractNo(contract.getContractNo());
            balanceSheetRecord.setProjectId(contract.getProjectId());
            balanceSheetRecord.setRoomId(contract.getRoomId());
            balanceSheetRecord.setHouseNum(room.getHouseNum());
            balanceSheetRecord.setContractId(contract.getId());

            balanceSheetRecord.setBillId(bill.getId());
            balanceSheetRecord.setBillNo(billTail.getDetailNo());
            balanceSheetRecord.setBillMonth(bill.getBillMonth());
            balanceSheetRecord.setBillName(bill.getName());
            balanceSheetRecord.setAmountReceived(0.00);
            balanceSheetRecord.setBillStatus(BillStatusEnum.BIST3.getCode());
            balanceSheetRecord.setBillType(LandeaConstants.BillType.MONTHLY_BILL);
            balanceSheetRecord.setExpenditureCode(billTail.getType());
            String expenditure = balanceSheetRecordReadMapper.selectExpenditure(billTail.getType());
            balanceSheetRecord.setExpenditure(getAuthCodeBillType(billTail.getType(), expenditure));
            balanceSheetRecord.setStartTime(billTail.getDateBegin());
            balanceSheetRecord.setReceivableMoney(billTail.getMoney());
            balanceSheetRecord.setEndTime(billTail.getDateEnd());
            balanceSheetRecord.setMark(billTail.getRemark());
            balanceSheetRecord.setProduceType(ProduceType.AUTHCODE);
            
            insertBalanceSheet(balanceSheetRecord);
        }
    }
    
    /**
     * 
     * [简要描述]：删除授权码记录</br>
     * [详细描述]：物理删除</br>
     * [作者]：Aaron(2017-10-20)</br>
     *
     * @param paramMap
     * @throws LandseaException
     *
     */
    public void deleteCouponRecord(Map<String,Object> paramMap)
        throws LandseaException
    {
        paramMap.put("produceType", ProduceType.AUTHCODE);
        balanceSheetWriteMapper.removeCoupon(paramMap);
    }
    
    /**
     * 
     * [简要描述]：物理删除预定独立账单</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-12-06)</br>
     *
     * @param depositId
     *
     */
    public void removeDepositBalance(Integer depositId)
    {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("contractId", depositId);
        map.put("billType", BTypeEnum._BT4.getCode());
        balanceSheetWriteMapper.removeDepositBalance(map);
    }
    
    /**
     * 
     * [简要描述]：物理删除月结账单的记录</br>
     * [详细描述]：物理删除,慎重调用 </br>
     * [作者]：Aaron(2017-10-20)</br>
     *
     * @param paramMap
     * @throws LandseaException
     *
     */
    public void removeFirstBillBalance(Map<String,Object> paramMap)
        throws LandseaException
    {
        paramMap.put("billType", BTypeEnum._BT1.getCode());
        balanceSheetWriteMapper.removeFirstBillBalance(paramMap);
    }
    
    /**
     * 
     * [简要描述]：独立账单</br>
     * [详细描述]：独立账单的修改操作</br>
     * [作者]：Crystal(2017-08-31)</br>
     *
     * @throws LandseaException
     *
     */
    // 预定
    public void depUpdateBalanceSheet(Integer depositId, String depositSn, Date payTime)
        throws LandseaException
    {
        Deposit deposit = depositReadMapper.selectByPrimaryKey(depositId);
        HashMap<String, Object> editBalanceSheet = new HashMap<String, Object>();
        editBalanceSheet.put("billId", depositId);
        editBalanceSheet.put("billType", LandeaConstants.BillType.RESERVE_BILL);
        editBalanceSheet.put("amountReceived", deposit.getDepositAmount());
        editBalanceSheet.put("billStatus", BillStatusEnum.BIST2.getCode());
        editBalanceSheet.put("payTime", payTime);
        editBalanceSheet.put("contractNo", depositSn);
        editBalanceSheet.put("lastModifiedBy", SecurityUtils.getCurrentLogin().getUserId());
        editBalanceSheet.put("lastModifiedDtm", new Date());
        
        balanceSheetWriteMapper.updateStatusBySelective(editBalanceSheet);
    }
    
    /**
     * 
     * [简要描述]：首期支付成功后，更新状态、合同编号、子账单编号、支付时间</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-09-25)</br>
     *
     * @param billId
     * @param contractNo
     * @param billDetail
     * @param payTime
     * @throws LandseaException
     *
     */
    public void firUpdateBalanceSheet(Integer billId, String contractNo, BillDetail billDetail, Date payTime)
        throws LandseaException
    {
        Bill bill = billReadMapper.selectKey(billId);
        HashMap<String, Object> editBalanceSheet = new HashMap<String, Object>();
        editBalanceSheet.put("billId", billId);
        editBalanceSheet.put("billType", LandeaConstants.BillType.FIRST_BILL);
        editBalanceSheet.put("billMonth", bill.getBillMonth());
        editBalanceSheet.put("expenditureCode", billDetail.getType());
        editBalanceSheet.put("billDetailId", billDetail.getId());
        
        editBalanceSheet.put("contractNo", contractNo);
        editBalanceSheet.put("billNo", billDetail.getDetailNo());
        editBalanceSheet.put("amountReceived", billDetail.getMoney());
        editBalanceSheet.put("billStatus", BillStatusEnum.BIST2.getCode());
        editBalanceSheet.put("payTime", payTime);
        editBalanceSheet.put("lastModifiedBy", SecurityUtils.getCurrentLogin().getUserId());
        editBalanceSheet.put("lastModifiedDtm", new Date());
        
        // 更新状态、金额、编号、支付时间
        balanceSheetWriteMapper.updateMonthPaied(editBalanceSheet);
    }
    
    // 月结
    public void monUpdateBalanceSheet(Integer billId, Date payTime)
        throws LandseaException
    {
        Bill bill = billReadMapper.selectKey(billId);
        List<BillDetail> billDetails = billDetailReadMapper.getBillDetail(billId);
        for (BillDetail billDetail : billDetails)
        {
            
            Map<String, Object> editRecord = new HashMap<String, Object>();
            editRecord.put("billId", billId);
            editRecord.put("billType", LandeaConstants.BillType.MONTHLY_BILL);
            editRecord.put("billMonth", bill.getBillMonth());
            editRecord.put("expenditureCode", billDetail.getType());
            List<BalanceSheetRecord> balanceSheetRecords = balanceSheetRecordReadMapper.selectEditRecord(editRecord);
            if (null == balanceSheetRecords)
            {
                continue;
            }
            for (BalanceSheetRecord balanceSheetRecord : balanceSheetRecords)
            {
                
                balanceSheetRecord.setAmountReceived(balanceSheetRecord.getReceivableMoney());
                balanceSheetRecord.setBillStatus(BillStatusEnum.BIST2.getCode());
                balanceSheetRecord.setPayTime(payTime);
                balanceSheetWriteMapper.updateByPrimaryKeySelective(balanceSheetRecord);
            }
        }
    }
    
    // 退租-月结
    public void monUpdateBalanceSheetRent(Integer contractId, Date payTime)
        throws LandseaException
    {
        Map<String, Object> editRecord = new HashMap<String, Object>();
        editRecord.put("contractId", contractId);
        editRecord.put("billStatus", BillStatusEnum.BIST2.getCode());
        editRecord.put("payTime", payTime);
        editRecord.put("lastModifiedDtm", new Date());
        editRecord.put("lastModifiedBy", SecurityUtils.getCurrentLogin().getUserId());
        balanceSheetWriteMapper.updateUnrentBillByContract(editRecord);
    }    
    
    // 实时
    public void realUpdateBalanceSheet(Integer billId, Date payTime)
        throws LandseaException
    {
        RealBill bill = realBillReadMapper.selectByPrimaryKey(billId);
        
        Map<String, Object> editRecord = new HashMap<String, Object>();
        editRecord.put("billId", billId);
        editRecord.put("billType", LandeaConstants.BillType.REALTIME_BILL);
        editRecord.put("billMonth", bill.getBillMonth());
        editRecord.put("expenditureCode", bill.getExpenseType());
        List<BalanceSheetRecord> balanceSheetRecords = balanceSheetRecordReadMapper.selectEditRecord(editRecord);
        
        if (null == balanceSheetRecords)
        {
            return;
        }
        
        for (BalanceSheetRecord balanceSheetRecord : balanceSheetRecords)
        {
            balanceSheetRecord.setAmountReceived(balanceSheetRecord.getReceivableMoney());
            //balanceSheetRecord.setProduceType(ProduceType.CANCEL);
            balanceSheetRecord.setBillStatus(BillStatusEnum.BIST2.getCode());
            balanceSheetRecord.setPayTime(payTime);
            balanceSheetWriteMapper.updateByPrimaryKeySelective(balanceSheetRecord);
        }
    }
    // 实时账单支付处理
    public void realPayBalanceSheet(Integer billId, Date payTime)
            throws LandseaException
    {
        RealBill bill = realBillReadMapper.selectByPrimaryKey(billId);

        Map<String, Object> editRecord = new HashMap<String, Object>();
        editRecord.put("billId", billId);
        editRecord.put("billType", LandeaConstants.BillType.REALTIME_BILL);
        editRecord.put("billMonth", bill.getBillMonth());
        editRecord.put("expenditureCode", bill.getExpenseType());
        List<BalanceSheetRecord> balanceSheetRecords = balanceSheetRecordReadMapper.selectEditRecord(editRecord);

        if (null == balanceSheetRecords)
        {
            return;
        }

        for (BalanceSheetRecord balanceSheetRecord : balanceSheetRecords)
        {
            if(balanceSheetRecord.getProduceType()==2){
                continue;
            }
            balanceSheetRecord.setAmountReceived(balanceSheetRecord.getReceivableMoney());
            balanceSheetRecord.setBillStatus(BillStatusEnum.BIST2.getCode());
            balanceSheetRecord.setPayTime(payTime);
            balanceSheetWriteMapper.updateByPrimaryKeySelective(balanceSheetRecord);
        }
    }
    // 滞纳金
    public void lateFeeUpdateBalanceSheetRent(CurrentBillDTO billDto, Double money, Date dateBegin, Date dateEnd,String billNo)
        throws LandseaException
    {
        Map<String, Object> editRecord = new HashMap<String, Object>();
        editRecord.put("billId", billDto.getId());
        editRecord.put("billMonth", billDto.getBillMonth());
        editRecord.put("expenditureCode", BillTypeEnum.CTBI13.getCode());
        
        // 先查询独立账单表是否存在滞纳金,只取第一个，因为只能查询出一条记录
       List<BalanceSheetRecord> balanceSheetRecords = balanceSheetRecordReadMapper.selectEditRecord(editRecord);
        
        if (balanceSheetRecords.size()==0)
        {
            log.info("新增滞纳金至独立账单表，billId ："+ billDto.getId());
            // 新增
            BalanceSheetRecord record = new BalanceSheetRecord();
            
            record.setBillId(billDto.getId());
            Contract contract = contractReadMapper.selectByPrimaryKey(billDto.getContractId());
            if (null != contract)
            {
                record.setContractNo(contract.getContractNo());
                record.setProjectId(contract.getProjectId());
                record.setRoomId(contract.getRoomId());
                record.setContractId(contract.getId());
                Room room = roomReadMapper.selectByPrimaryKey(contract.getRoomId());
                record.setHouseNum(room.getHouseNum());
            }
            record.setBillMonth(billDto.getBillMonth());
            record.setBillName(billDto.getName());
            record.setBillNo(billNo);
            record.setExpenditureCode(BillTypeEnum.CTBI13.getCode());
            record.setExpenditure(BillTypeEnum.CTBI13.getName());
            record.setStartTime(dateBegin);
            record.setEndTime(dateEnd);
            record.setReceivableMoney(money);
            record.setAmountReceived(0.00);
            record.setBillStatus(BillStatusEnum.BIST3.getCode());
            record.setBillType(BTypeEnum._BT2.getCode());
            record.setProduceType(ProduceType.PAY);
            insertBalanceSheet(record);
            
            return ;
        }
        
        // 修改,不会改状态，状态在支付地方改,这里只修改钱
        for (BalanceSheetRecord balanceSheetRecord : balanceSheetRecords)
        {
            log.info("修改滞纳金至独立账单表，balanceSheetRecord id ："+ balanceSheetRecord.getId());
            BalanceSheetRecord update = new BalanceSheetRecord();
            update.setId(balanceSheetRecord.getId());
            update.setReceivableMoney(money);
            update.setEndTime(new Date());
            update.setLastModifiedBy(SecurityUtils.getCurrentLogin().getUserId());
            update.setLastModifiedDtm(new Date());
            balanceSheetWriteMapper.updateByPrimaryKeySelective(update);
        }
    }
    
    /**
     * 
     * [简要描述]：授权码费项的名称</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-10-26)</br>
     *
     * @param billType
     * @param expenditure
     * @return
     *
     */
    public String getAuthCodeBillType(String billType, String expenditure)
    {
        String result = AuthCodeBillTypeGetter.getBillTypeZh(billType);
        if (null == result)
        {
            result = "优惠";
        }
        
        return expenditure + result;
    }
    
    // 首期账单时构造独立账单,入库
    public BalanceSheetRecord buildFirstBillBalanceRecord(Contract contract, Bill parBill, BillDetail billTail)
    {
        // 往balanceSheet中加备份
        BalanceSheetRecord record = new BalanceSheetRecord();
        record.setContractNo(contract.getContractNo());
        record.setProjectId(contract.getProjectId());
        record.setRoomId(contract.getRoomId());
        record.setContractId(contract.getId());
        
        record.setBillId(parBill.getId());
        record.setBillMonth(parBill.getBillMonth());
        record.setBillName(parBill.getName());
        record.setAmountReceived(0.00);
        record.setBillStatus(BillStatusEnum.BIST3.getCode());
        record.setBillType(LandeaConstants.BillType.FIRST_BILL);
        
        record.setExpenditureCode(billTail.getType());
        record.setReceivableMoney(billTail.getMoney());
        record.setEndTime(billTail.getDateEnd());
        record.setMark(billTail.getRemark());
        
        // 如果是授权码
        String expenditure = balanceSheetRecordReadMapper.selectExpenditure(billTail.getType());
        if (null != billTail.getCouponFlag() && billTail.getCouponFlag().booleanValue())
        {
            record.setExpenditure(getAuthCodeBillType(billTail.getType(), expenditure));
            record.setProduceType(ProduceType.AUTHCODE);
            
        }
        else
        {
            record.setExpenditure(expenditure);
            record.setProduceType(ProduceType.PAY);
        }
        
        return record;
    }
}
